package com.leviassaf.speaktranslation;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Bundle;
import android.speech.RecognitionListener;
import android.speech.RecognizerIntent;
import android.speech.SpeechRecognizer;
import android.speech.tts.TextToSpeech;
import android.speech.tts.UtteranceProgressListener;
import android.speech.tts.TextToSpeech.OnInitListener;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;

import com.memetix.mst.language.Language;
import com.memetix.mst.translate.Translate;

@SuppressLint("NewApi")
public class MyTextToSpeech extends Activity implements OnInitListener,
		OnClickListener, OnItemSelectedListener, Communicator, TextWatcher {

	boolean booUserTextChanged = false;
	private TextToSpeech tts;
	Button btnSpeak, btnCancel, btnRecognizeSpeech;
	EditText edtTranslatedText;
	EditText edtUserText;
	Spinner spinner;
	private String[] arrStrlanguages;
	private List<String> listStrLanguages = new ArrayList<String>();
	private ArrayAdapter<String> languagesAdapter;
	private String curLang;
	String strTranslatedText = "";
	Language languageTarget = Language.ENGLISH;
	String strUserText = "";
	String[] arrStrLocaleInfo;
	LanguageInfo[] langinfo;

	UtteranceProgressListener utteranceProgressListener = new UtteranceProgressListener() {
		@Override
		public void onDone(String utteranceId) {

			MyTextToSpeech.this.runOnUiThread(new Runnable() {

				@Override
				public void run() {
					btnCancel.setVisibility(View.GONE);
					btnSpeak.setVisibility(View.VISIBLE);
					btnSpeak.setEnabled(true);
				}
			});
		}

		@Override
		public void onError(String utteranceId) {

		}

		@Override
		public void onStart(String utteranceId) {

		}

	};

	@Override
	protected void onDestroy() {
		// Close the Text to Speech Library
		if (tts != null) {

			tts.stop();
			tts.shutdown();
		}
		super.onDestroy();
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.texttospeech);
		arrStrlanguages = getResources()
				.getStringArray(R.array.arrStrlanguages);
		Arrays.sort(arrStrlanguages);

		setJavaRefs();

		this.setTitle(String.format("%s", this.getTitle().toString()));

		tts = new TextToSpeech(this, this);
		tts.setOnUtteranceProgressListener(utteranceProgressListener);
	}

	private void setJavaRefs() {
		edtTranslatedText = (EditText) findViewById(R.id.txtvwTranslatedText);
		TextView txtvwUserText = (TextView) findViewById(R.id.txtvwUserText);
		edtUserText = (EditText) findViewById(R.id.edtUserText);
		edtUserText.addTextChangedListener(this);
		spinner = (Spinner) findViewById(R.id.spinner);
		btnSpeak = (Button) findViewById(R.id.btnSpeak);
		btnSpeak.setOnClickListener(this);
		btnCancel = (Button) findViewById(R.id.btnCancel);
		btnCancel.setOnClickListener(this);
		btnRecognizeSpeech = (Button) findViewById(R.id.btnRecognizeSpeech);
		btnRecognizeSpeech.setOnClickListener(this);
		spinner.setOnItemSelectedListener(this);
		txtvwUserText.setTextColor(Color.rgb(255, 153, 0));
	}

	public String translate(String text) throws Exception {
		// Set the Client ID / Client Secret once per JVM. It is set statically
		// and applies to all services
		Translate.setClientId(getString(R.string.translation_client_id));
		Translate
				.setClientSecret(getString(R.string.translation_client_secret));

		strTranslatedText = Translate.execute(text, languageTarget);

		return strTranslatedText;
	}

	@Override
	public void onInit(int status) {
		populateSupportedTargetLanguages(status);
	}

	private void populateSupportedTargetLanguages(int status) {
		Locale locale = null;
		if (status == TextToSpeech.SUCCESS) {

			listStrLanguages.add("Select Language");
			langinfo = new LanguageInfo[arrStrlanguages.length];
			for (int i = 0; i < arrStrlanguages.length; i++) {
				arrStrLocaleInfo = arrStrlanguages[i].split("\\|");
				langinfo[i] = new LanguageInfo();
				langinfo[i].setLanguageName(arrStrLocaleInfo[0].toString());
				langinfo[i].setLanguageCode(arrStrLocaleInfo[1].toString());
				langinfo[i].setCountryCode(arrStrLocaleInfo[2].toString());
				locale = new Locale(langinfo[i].getLanguageCode(),
						langinfo[i].getCountryCode());
				if (tts.isLanguageAvailable(locale) == TextToSpeech.LANG_COUNTRY_AVAILABLE
						|| langinfo[i].getLanguageCode().contentEquals("ru")
						|| langinfo[i].getLanguageCode().contentEquals("hi")) {
					if (listStrLanguages.indexOf(langinfo[i].getLanguageName()) == -1) {
						listStrLanguages.add(langinfo[i].getLanguageName());
					}
				}
			}

			languagesAdapter = new ArrayAdapter<String>(MyTextToSpeech.this,
					android.R.layout.simple_spinner_dropdown_item,
					listStrLanguages);
			languagesAdapter
					.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
			spinner.setAdapter(languagesAdapter);
			btnSpeak.setEnabled(true);
		} else {
			Log.e("TTS", "Initilization Failed!");
		}

	}

	private void speakOut(String text) {
		HashMap<String, String> hashMapParams = new HashMap<String, String>();
		hashMapParams.put(TextToSpeech.Engine.KEY_PARAM_UTTERANCE_ID,
				"end_of_translation");
		tts.speak(strTranslatedText, TextToSpeech.QUEUE_FLUSH, hashMapParams);
	}

	private int SetLanguage(String lang) {
		int result = 0;
		Locale locale;

		for (int i = 0; i < langinfo.length; i++) {
			if (lang.startsWith(langinfo[i].getLanguageName())) {
				locale = new Locale(langinfo[i].getLanguageCode(),
						langinfo[i].getCountryCode());
				result = tts.setLanguage(locale);
				break;
			}
		}

		if (lang.startsWith("French")) {
			languageTarget = Language.FRENCH;
		} else if (lang.startsWith("Spanish")) {
			languageTarget = Language.SPANISH;
		} else if (lang.startsWith("English")) {
			languageTarget = Language.ENGLISH;
		} else if (lang.startsWith("German")) {
			languageTarget = Language.GERMAN;
		} else if (lang.startsWith("Italian")) {
			languageTarget = Language.ITALIAN;
		} else if (lang.startsWith("Russian")) {
			languageTarget = Language.RUSSIAN;
		} else if (lang.startsWith("Romanian")) {
			languageTarget = Language.ROMANIAN;
		} else if (lang.startsWith("Hebrew")) {
			languageTarget = Language.HEBREW;
		} else if (lang.startsWith("Turkish")) {
			languageTarget = Language.TURKISH;
		} else if (lang.startsWith("Portuguese")) {
			languageTarget = Language.PORTUGUESE;
		} else if (lang.startsWith("Dutch")) {
			languageTarget = Language.DUTCH;
		} else if (lang.startsWith("Japanese")) {
			languageTarget = Language.JAPANESE;
		} else if (lang.startsWith("Korean")) {
			languageTarget = Language.KOREAN;
		} else if (lang.startsWith("Chinese")) {
			languageTarget = Language.CHINESE_SIMPLIFIED;
		} else if (lang.startsWith("Arabic")) {
			languageTarget = Language.ARABIC;
		} else if (lang.startsWith("Bulgarian")) {
			languageTarget = Language.BULGARIAN;
		} else if (lang.startsWith("Catalan")) {
			languageTarget = Language.CATALAN;
		} else if (lang.startsWith("Czech")) {
			languageTarget = Language.CZECH;
		} else if (lang.startsWith("Danish")) {
			languageTarget = Language.DANISH;
		} else if (lang.startsWith("Greek")) {
			languageTarget = Language.GREEK;
		} else if (lang.startsWith("Finnish")) {
			languageTarget = Language.FINNISH;
		} else if (lang.startsWith("Hindi")) {
			languageTarget = Language.HINDI;
		} else if (lang.startsWith("Hungarian")) {
			languageTarget = Language.HUNGARIAN;
		} else if (lang.startsWith("Indonesian")) {
			languageTarget = Language.INDONESIAN;
		} else if (lang.startsWith("Lithuanian")) {
			languageTarget = Language.LITHUANIAN;
		} else if (lang.startsWith("Latvian")) {
			languageTarget = Language.LATVIAN;
		} else if (lang.startsWith("Norwegian")) {
			languageTarget = Language.NORWEGIAN;
		} else if (lang.startsWith("Polish")) {
			languageTarget = Language.POLISH;
		} else if (lang.startsWith("Slovak")) {
			languageTarget = Language.SLOVAK;
		} else if (lang.startsWith("Slovenian")) {
			languageTarget = Language.SLOVENIAN;
		} else if (lang.startsWith("Swedish")) {
			languageTarget = Language.SWEDISH;
		} else if (lang.startsWith("Thai")) {
			languageTarget = Language.THAI;
		} else if (lang.startsWith("Ukrainian")) {
			languageTarget = Language.UKRAINIAN;
		} else if (lang.startsWith("Vietnamese")) {
			languageTarget = Language.VIETNAMESE;
		} else {
			locale = new Locale("en");
			result = tts.setLanguage(locale);
			languageTarget = Language.ENGLISH;
		}
		return result;
	}

	@Override
	public void onClick(View v) {
		switch (v.getId()) {
		case R.id.btnSpeak:
			translateAndSpeak(edtUserText.getText().toString());
			break;
		case R.id.btnRecognizeSpeech:
			SpeechRecognizer sr = SpeechRecognizer
					.createSpeechRecognizer(getApplicationContext());
			MyRecognitionListener listener = new MyRecognitionListener(this);
			sr.setRecognitionListener(listener);
			sr.startListening(RecognizerIntent
					.getVoiceDetailsIntent(getApplicationContext()));

			break;
		case R.id.btnCancel:
			tts.stop();
			btnCancel.setVisibility(View.GONE);
			btnSpeak.setVisibility(View.VISIBLE);
			btnSpeak.setEnabled(true);
			break;
		}
	}

	private void translateAndSpeak(final String textToHandle) {
		btnSpeak.setEnabled(false);
		SetLanguage(curLang);

		// strUserText = edtUserText.getText().toString();

		edtTranslatedText.setVisibility(View.VISIBLE);
		edtTranslatedText.setTextColor(Color.rgb(255, 153, 0));

		class bgStuff extends AsyncTask<String, String, String> {
			@Override
			protected String doInBackground(String... params) {
				publishProgress("Translating...");
				try {
					if (booUserTextChanged) {
						strTranslatedText = translate(textToHandle);
						booUserTextChanged = false;
					}
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					strTranslatedText = "Unable to get translation. Please check your internet connection.";
				}

				return strTranslatedText;
			}

			protected void onProgressUpdate(String... values) {
				edtTranslatedText.setText(values[0]);
			}

			@Override
			protected void onPostExecute(String result) {
				super.onPostExecute(result);

				edtTranslatedText.setText(result);
				if (!result.contentEquals("")) {
					btnSpeak.setVisibility(View.GONE);
					btnCancel.setVisibility(View.VISIBLE);
					speakOut(result);
				}
			}

		}

		new bgStuff().execute();
	}

	@Override
	public void onItemSelected(AdapterView<?> adapter, View view, int position,
			long id) {
		curLang = (String) spinner.getAdapter().getItem((int) id);
	}

	@Override
	public void onNothingSelected(AdapterView<?> arg0) {
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		super.onCreateOptionsMenu(menu);
		MenuInflater mnuinflaterBlowUp = getMenuInflater();
		mnuinflaterBlowUp.inflate(R.menu.cool_menu, menu);
		return true;
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		Intent intent;
		switch (item.getItemId()) {
		case R.id.mnuitmAbout:
			intent = new Intent("com.leviassaf.speaktranslation.ABOUT");
			startActivity(intent);
			break;
		case R.id.mnuitmPreferences:
			intent = new Intent("com.leviassaf.speaktranslation.PREFS");
			startActivity(intent);
			break;
		case R.id.mnuitmExit:
			finish();
			break;
		}
		return false;
	}

	@Override
	public void sendMessage(String message) {
		edtUserText.setText(message);
		translateAndSpeak(message);
	}

	class MyRecognitionListener implements RecognitionListener {
		Communicator communicator;

		public MyRecognitionListener(Activity callingActivity) {
			communicator = (Communicator) callingActivity;
		}

		@Override
		public void onBeginningOfSpeech() {
		}

		@Override
		public void onBufferReceived(byte[] buffer) {
		}

		@Override
		public void onEndOfSpeech() {
		}

		@Override
		public void onError(int error) {
		}

		@Override
		public void onEvent(int eventType, Bundle params) {
		}

		@Override
		public void onPartialResults(Bundle partialResults) {
		}

		@Override
		public void onReadyForSpeech(Bundle params) {
		}

		@Override
		public void onResults(Bundle results) {
			ArrayList<String> strlist = results
					.getStringArrayList(SpeechRecognizer.RESULTS_RECOGNITION);
			communicator.sendMessage(strlist.get(0));
		}

		@Override
		public void onRmsChanged(float rmsdB) {
		}

	}

	@Override
	public void afterTextChanged(Editable s) {
		booUserTextChanged = true;
	}

	@Override
	public void beforeTextChanged(CharSequence s, int start, int count,
			int after) {
	}

	@Override
	public void onTextChanged(CharSequence s, int start, int before, int count) {
	}
}
